#ifndef ThreadPool_INCLUDED
#define ThreadPool_INCLUDED

#include "thread.h"
#include "mutex.h"
#include <list>

using std::list;
class Runnable;
class PooledThread;
static const int DEFAULT_STACK_SIZE = 4*1024*1024;
class ThreadPool
{
public:
    ThreadPool(unsigned int minCapacity = 2,
        unsigned int maxCapacity = 16,
        int idleTime = 60,
        unsigned int stackSize = DEFAULT_STACK_SIZE);

    ThreadPool(const std::string& name,
        unsigned int minCapacity = 2,
        unsigned int maxCapacity = 16,
        int idleTime = 60,
        unsigned int stackSize = DEFAULT_STACK_SIZE);

    ~ThreadPool();
    
    void addCapacity(int n);

    int capacity();

    void setStackSize(int stackSize);

    int getStackSize();

    int working();

    int allocated();

    int available();

    bool start(Runnable& target);
        /// 是否真正启动，可能线程不够了

    void stopAll();
        /// 立即停止正在运行的线程
    
	void joinAll();
        /// 仅清理已运行完的线程
    
    void joinTimeoutWorkingThread(unsigned int second);
        /// close working thread than working more than timeout second.
    
    std::string& name();

    static ThreadPool& defaultPool();

protected:
    PooledThread* getThread();
    PooledThread* createThread();
    void          clearIdle();  /// clear idle thread
    void          adjustIdleWorking(); // 整理队列
private:
    ThreadPool(const ThreadPool& pool);
    ThreadPool& operator = (const ThreadPool& pool);

private:
    typedef std::list<PooledThread*> ThreadList;
    
    std::string         m_name;
    int                 m_minCapacity;
    int                 m_maxCapacity;
    int                 m_idleTime;
    int                 m_stackSize;
    ThreadList          m_idleThreads;
    ThreadList          m_workingThreads;
    mutable Mutex       m_mutex;
};

//
// inlines
//
inline void ThreadPool::setStackSize(int stackSize)
{
    m_stackSize = stackSize;
}

inline int ThreadPool::getStackSize()
{
    return m_stackSize;
}

inline std::string& ThreadPool::name()
{
    return m_name;
}


#endif
